/**
  ******************************************************************************
  * @file    main.c
  * @author  
  * @version V1.1
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2018 Shanghai Macrogiga Electronics</center></h2>
  *
  ******************************************************************************
  */
#include "mg_driver.h"
#include "mg_driver_pwm.h"
#include "mg_driver_pwm_led.h"


#define LED_NUM (5) //LED lamp number, one may change this.

#define LED_total_number (LED_NUM*3/*RGB_BYTE*/)/*RGB bytes number*/
#define LED_DATA_LEN (3*5) /*ping-pong buffer size(byte)*/

u32 pwm_led_data0[LED_DATA_LEN/4+1] = {0}; //MUST 32bit aligned
u32 pwm_led_data1[LED_DATA_LEN/4+1] = {0}; //MUST 32bit aligned

//test colors
u8 LED_RGB_Value[LED_total_number] = {
    0,255,0,   //GGRRBB
    255,0,0,
    0,0,255,
    0,255,255,
    255,255,0
};

#define CORE_CLK  39/*Mhz*/

#if 0 //SK6805

    #define DutyCycleCount (CORE_CLK * 5/4)     /*0x30*/
    #define DutyCount0     (CORE_CLK * 3/10)    /*0x0C*/
    #define DutyCount1     (CORE_CLK * 6/10)    /*0x18*/
    #define RstCount       (CORE_CLK * 80)      /*0x0c80*/

#else //WS2811

/*
T1H 580ns~1.6us  -->1.0us
T1L 220ns~420ns  -->0.3us

T0H 220ns~380ns  -->0.3us
T0L 580ns~1.6us  -->1.0us
RES 280 us*/

    #define DutyCycleCount (CORE_CLK * 13/10)
    #define DutyCount0     (CORE_CLK * 3/10)
    #define DutyCount1     (CORE_CLK * 10/10)
    #define RstCount       (CORE_CLK * 280)

#endif

void PWM_LED_filldata(u8 FirstFlag)
{
    static int LED_pos_idx = 0;//byte position
    static int LED_fifo_idx = 0;
    
    static char data_offset = 0;
    static int delay_count = 0;
    
    u8* data_p;
    int len;
    
    if(FirstFlag)
    {
        LED_pos_idx = 0;
        LED_fifo_idx = 0;
        
        delay_count ++;
        if(delay_count == 500)
        {
            data_offset += 3; //shift one led's data
            data_offset %= LED_total_number;
            
            delay_count = 0;
        }
    }
    if(LED_pos_idx >= LED_total_number)return;//end
    
    if(LED_fifo_idx)
        data_p = (u8*)pwm_led_data1;
    else
        data_p = (u8*)pwm_led_data0;
    
    len = 0;//byte
    while(LED_pos_idx < LED_total_number)
    {        
        *data_p++ = LED_RGB_Value[(data_offset+LED_pos_idx)%LED_total_number];LED_pos_idx ++;
        len ++;
        if(len >= LED_DATA_LEN)break; //end of buffer filling
    }
    
    if(LED_pos_idx >= LED_total_number) len |= (0x01<<10);//end
    
    if(LED_fifo_idx)
        PWM_LED_UpdateDataLen1(len,0);
    else
        PWM_LED_UpdateDataLen0(len,0);
    
    LED_fifo_idx = !LED_fifo_idx;
}

static void demo_pwm_led(void)
{
    NVIC_IrqClearPendingIRQ(BBSeg_IRQn);
    NVIC_EnableIRQ(INT_MASK_BIT_PWM_LED);//enable irq, keep the highest priority,defualt is 0(highest)
    
    PWM_LED_Init((u32)pwm_led_data0, (u32)pwm_led_data1, DutyCycleCount, DutyCount0, DutyCount1, RstCount);
    
    PWM_LED_filldata(1);
    PWM_LED_filldata(0);
    
    PWM_LED_Start();
}

int main(void)
{
    demo_pwm_led();

    while(1);
}
